
`include "common_header.verilog"

//  *************************************************************************
//  File : gray_cnt.v
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized reproduction or use is expressly prohibited. 
//  Copyright (c) 2002-2003-2004 Morethanip
//  An der Steinernen Brueke 1, 85757 Karlsfeld, Germany
//  Designed by Francois Balay
//  info@morethanip.com
//  *************************************************************************
//  Decription : Multicast Address Resolution - Byte Serial Implementation
//  Version    : $Id: gray_cnt_xgxs.v,v 1.3 2017/06/07 14:37:54 dk Exp $
//  *************************************************************************

module gray_cnt_xgxs (clk,
`ifdef USE_CLK_ENA
   clk_ena,
`endif  
   reset,
   sync_rst,
   enable,
   b_out,
   g_out);
   
parameter ADDR_WIDTH = 3'b 111;
parameter DEPTH = 8'b 10000000;

input   clk; 
`ifdef USE_CLK_ENA
input   clk_ena;
`endif 
input   reset;
input   sync_rst; 
input   enable; 
output  [ADDR_WIDTH - 1:0] b_out; 
output  [ADDR_WIDTH - 1:0] g_out; 

reg     [ADDR_WIDTH - 1:0] b_out; 
reg     [ADDR_WIDTH - 1:0] g_out; 
reg     [ADDR_WIDTH - 1:0] b_int;
wire    [ADDR_WIDTH - 1:0] b_slv; 

wire    [ADDR_WIDTH - 1:0]  gry_grayval; 

`define GRAY_CNT_HEX_VAL1 {ADDR_WIDTH{1'b 1}}
`define GRAY_CNT_HEX_VAL2 {{ADDR_WIDTH-1{1'b 0}}, 1'b1}
`define GRAY_CNT_HEX_VAL3 {{ADDR_WIDTH-1{1'b 1}}, 1'b0}

always @(posedge clk or posedge reset)
   begin : bin
   if (reset == 1'b 1)
      begin
      b_int[ADDR_WIDTH-1:1] <= {ADDR_WIDTH-1{1'b 0}};	
      b_int[0]              <= 1'b1 ;	
      end
   else
      begin

         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif
        
                if (sync_rst==1'b1)
                begin
                
                        b_int[ADDR_WIDTH-1:1] <= {ADDR_WIDTH-1{1'b 0}};	
                        b_int[0]              <= 1'b1 ;
              
                end
                else
                begin
              
                        if (enable == 1'b 1)
                        begin
                                if (b_int < `GRAY_CNT_HEX_VAL1)
                                begin
                                        
                                        b_int <= (b_int + `GRAY_CNT_HEX_VAL2);	
                                        
                                end
                                else
                                begin
                                
                                        b_int <= {ADDR_WIDTH{1'b 0}};
                                        	
                                end
                        end
                end
      
         `ifdef USE_CLK_ENA
            end
         `endif       
      
      end
   end

assign b_slv = b_int;

//  Binary next generation to run according the gray values
//  -------------------------------------------------------

always @(posedge clk or posedge reset)
   begin : binreg
   if (reset == 1'b 1)
      begin
      b_out <= {ADDR_WIDTH{1'b 0}};	
      end
   else
      begin
      
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif        
        
                if (sync_rst==1'b1)
                begin
                
                        b_out <= {ADDR_WIDTH{1'b 0}};
                
                end
                else
                begin
              
                        if (enable == 1'b 1)
                        begin
                                
                                b_out <= b_slv;	
                 
                        end
                end
      
         `ifdef USE_CLK_ENA
            end
         `endif      
      
      end
   end

//  Binary to Gray Code conversion with additional Registers
//  --------------------------------------------------------

assign gry_grayval = bin2gray(b_slv) ;

always @(posedge clk or posedge reset)
   begin : gry
   if (reset == 1'b 1)
      begin
      g_out <= {ADDR_WIDTH{1'b 0}};	
      end
   else
      begin
      
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif        
        
                if (sync_rst==1'b1)
                begin
                
                        g_out <= {ADDR_WIDTH{1'b 0}};	
                
                end
                else
                begin
              
                        if (enable == 1'b 1)
                        begin
                 
                                g_out <= gry_grayval;	
                 
                        end
                        
                end
      
         `ifdef USE_CLK_ENA
            end
         `endif      
      
      end
   end

// Binany to Gray Conversion
// -------------------------

function [ADDR_WIDTH-1:0] bin2gray;

        input [ADDR_WIDTH-1:0]  bin_val ;
        
        integer LOOP_INDEX; 
                
        for (LOOP_INDEX = 0; LOOP_INDEX <= ADDR_WIDTH - 1; LOOP_INDEX = LOOP_INDEX + 1)
        begin
            
                if (LOOP_INDEX == ADDR_WIDTH - 1'b 1)
                begin
               
                        bin2gray[LOOP_INDEX] = bin_val[LOOP_INDEX];	
               
                end
                else
                begin
               
                        bin2gray[LOOP_INDEX] = b_slv[LOOP_INDEX + 1] ^ bin_val[LOOP_INDEX];	
               
                end
        
        end
        
endfunction

endmodule // module gray_cnt